﻿#include "wsignalserver.h"
#include "log4z.h"
#include "cmainframe.h"

#include <random>

wxDEFINE_EVENT(EVENT_CLIENT_CLOSED, wxThreadEvent);
initialiseSingleton(WSignalServer);

ClientInfo::ClientInfo(wxString cName,
                       WSignalServer *cServer)
    : socket(NULL),
      clientName(cName),
      isProcessMsgHearder(false),
      errorCount(0)
{

}

ClientInfo::~ClientInfo()
{
    this->deleteMe();
}

bool ClientInfo::SendData(int msgtype,const void* data,size_t len)
{
    if (socket == NULL || !socket->IsConnected())
        return false;

    tagMsgHearder decMsgHearder;
    memset(&decMsgHearder,0,sizeof(tagMsgHearder));
    decMsgHearder.msgType = msgtype;
    decMsgHearder.mark[0] = 'M';
    decMsgHearder.mark[1] = 'O';
    decMsgHearder.mark[2] = 'N';

    if(data == NULL || len <= 0)
    {
        this->Send(&decMsgHearder,sizeof(tagMsgHearder));
        return true;
    }

    decMsgHearder.checknum = qChecksum((const char*)data,len);
    decMsgHearder.srcLength = len;

    wxMemoryBuffer comBuffer = CompressWithFastLZ(data,len);
    decMsgHearder.compLength = comBuffer.GetDataLen();

    this->Send(&decMsgHearder,sizeof(tagMsgHearder));
    this->Send(comBuffer.GetData(),comBuffer.GetDataLen());

    return true;
}

bool ClientInfo::Send(const void* data, size_t len)
{
    if (socket == NULL || !socket->IsConnected())
        return false;

    int curSendPos = 0;

    while(curSendPos < len)
    {
        socket->Write((const char*)data+curSendPos, len-curSendPos);

        if (socket->LastError() != wxSOCKET_NOERROR)
            return false;

        curSendPos += socket->LastCount();
    }

    return true;
}

void ClientInfo::deleteMe(void)
{
    if(socket) { socket->Close(); socket->Destroy(); }
    socket = NULL;
}

/////////////////////////////////////////////////////////////////////////////

WSignalServer::WSignalServer(wxString ip,int port)
    : m_ServerIP(ip),
      m_ServerPort(port),
      m_signalserver(NULL),
      m_NetworkFrameManager(NULL),
      m_sendbufsize(1024),
      m_curOperClient(NULL)
{
    m_HeartTimeOutTimer = new wxTimer(this, wxID_ANY);
    this->Bind(wxEVT_TIMER, &WSignalServer::OnHeartTimeOutTimer, this);

    this->Bind(wxEVT_SOCKET, &WSignalServer::OnServerEvent, this);
    this->Bind(EVENT_CLIENT_CLOSED, &WSignalServer::OnClientClosedEvent, this);
}

WSignalServer::~WSignalServer()
{
    Close();
}

/// 打开服务器
bool WSignalServer::Open(void)
{
    if(m_ServerIP == "" || m_ServerPort <= 0)
        return false;

    if(m_signalserver != NULL)
        this->Close();

    // 创建地址对象
    wxIPV4address addr;
    if (!m_ServerIP.empty()) {
        addr.Hostname(m_ServerIP);  // 绑定到指定IP
    } else {
        addr.AnyAddress();   // 如果IP为空，则绑定到所有接口
    }
    addr.Service(m_ServerPort);      // 设置端口

    // 创建服务器
    m_signalserver = new wxSocketServer(addr, wxSOCKET_WAITALL | wxSOCKET_REUSEADDR);

    if (!m_signalserver->IsOk()) {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                            wxString::Format("WSignalServer::Open:Could not create server socket on %s:%d", m_ServerIP, m_ServerPort).ToUTF8());
        delete m_signalserver;
        m_signalserver = nullptr;
        return false;
    }

    CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,
                                        wxString::Format(wxT("信号服务器启动成功,侦听 %s:%d"),
                                        m_ServerIP.empty() ? "0.0.0.0" : m_ServerIP,
                                        m_ServerPort).ToUTF8());

    // 设置事件处理
    m_signalserver->SetEventHandler(*this);
    m_signalserver->SetNotify(wxSOCKET_CONNECTION_FLAG);
    m_signalserver->Notify(true);

    if(m_HeartTimeOutTimer)
        m_HeartTimeOutTimer->Start(10000); // 10秒

    return true;
}

/// 关闭服务器
void WSignalServer::Close(void)
{
    std::unique_lock lock(m_clientsMutex);
    std::map<wxSocketBase*, ClientInfo*>::iterator iter = m_clients.begin();
    for(;iter != m_clients.end();++iter)
    {
        delete (*iter).second;
        (*iter).second = NULL;
    }
    m_clients.clear();

    if(m_signalserver)
    {
        m_signalserver->Close();
        m_signalserver->Destroy();
    }
    m_signalserver = NULL;

    if(m_HeartTimeOutTimer)
        m_HeartTimeOutTimer->Stop();
}

/// 设置服务器IP和端口
bool WSignalServer::setServerParams(wxString ip,int port)
{
    //if(m_ServerIP == ip && m_ServerPort == port)
    //    return false;

    m_ServerIP = ip;
    m_ServerPort = port;

    return true;
}

void WSignalServer::OnServerEvent(wxSocketEvent& event)
{
    wxSocketBase* sock = event.GetSocket();

    switch(event.GetSocketEvent()) {
    case wxSOCKET_CONNECTION:
        OnClientConnected(sock);
        break;
    case wxSOCKET_INPUT:
        OnSocketData(sock);
        break;
    case wxSOCKET_LOST:
        OnClientDisconnected(sock);
        break;
    default:
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                            "WMonitoringServer::OnServerEvent:Unknown server event");
        break;
    }
}

void WSignalServer::OnClientClosedEvent(wxThreadEvent& event)
{
    ClientInfo *pClientInfo = this->FindClientName(event.GetString());
    if(pClientInfo != NULL)
        this->OnClientDisconnected(pClientInfo->socket);
}

void WSignalServer::OnClientConnected(wxSocketBase* serverSock)
{
    // 需要将 serverSock 转换为 wxSocketServer 指针
    wxSocketServer* server = dynamic_cast<wxSocketServer*>(serverSock);
    if (!server) {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                            "Invalid server socket");
        return;
    }

    // 使用 wxSocketServer 的 Accept 方法
    wxSocketBase* clientSock = server->Accept(false);

    if (!clientSock) {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                            "Failed to accept client connection");
        return;
    }

    wxIPV4address clientAddr;
    wxString clientId;
    if (clientSock->GetPeer(clientAddr)) {
        clientId = wxString::Format("%s:%d",
                  clientAddr.IPAddress(),
                  clientAddr.Service());
        //CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,
        //                                    wxString::Format("%s 连接成功,当前连接数量:%d", clientId,(int)m_clients.size()+1));
    } else {
        clientId = wxString::Format("unknown_%p", clientSock);
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                            "WSignalServer::OnClientConnected:Client connected (unknown address)");
    }

    clientSock->SetEventHandler(*this);
    clientSock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
    clientSock->Notify(true);

    // 设置非阻塞和超时
    clientSock->SetFlags(wxSOCKET_NOWAIT);
    clientSock->SetTimeout(5);  // 5秒超时

    // 添加新客户端到映射表
    ClientInfo *info = new ClientInfo(clientId,
                                      this);
    info->socket = clientSock;
    info->lastActiveTime = wxDateTime::Now();
    info->isProcessMsgHearder = false;
    info->errorCount = 0;

    // 先释放锁再回调
    {
        std::unique_lock lock(m_clientsMutex);
        m_clients[clientSock] = info;
    }

    CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,
                                        wxString::Format(wxT("%s连接成功,当前连接数量:%d"),
                                                         clientId,
                                                         (int)m_clients.size()).ToUTF8());

    // 网络框架处理json消息
    if(m_NetworkFrameManager)
        m_NetworkFrameManager->OnProcessConnectedNet(info);
}

void WSignalServer::OnSocketData(wxSocketBase* clientSock)
{
    // 查找客户端ID
    ClientInfo* decClientInfo = FindClientId(clientSock);
    if (decClientInfo == NULL) {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                            "Received data from unknown client");
        return;
    }

    // 更新最后活动时间
    decClientInfo->lastActiveTime = wxDateTime::Now();

    while (clientSock->IsData())
    {
        char buffer[4096];
        clientSock->Read(buffer, sizeof(buffer)-1);
        size_t bytesRead = clientSock->LastCount();

        if (bytesRead == 0) {
            OnClientDisconnected(clientSock);
            return;
        }

        if(decClientInfo->buffer.GetBufSize()+bytesRead > decClientInfo->buffer.GetBufSize())
            decClientInfo->buffer.SetBufSize(decClientInfo->buffer.GetBufSize()+bytesRead);

        decClientInfo->buffer.AppendData(buffer,bytesRead);
    }

    while(!decClientInfo->buffer.IsEmpty())
    {
        // 先处理消息头
        if(decClientInfo->buffer.GetDataLen() >= sizeof(tagMsgHearder) &&
           decClientInfo->isProcessMsgHearder == false)
        {
            memcpy(&decClientInfo->mMsgHearder,decClientInfo->buffer.GetData(),sizeof(tagMsgHearder));
            decClientInfo->RemoveDataFromMemoryBuffer(0,sizeof(tagMsgHearder));

            if(decClientInfo->mMsgHearder.mark[0] != 'M' ||
               decClientInfo->mMsgHearder.mark[1] != 'O' ||
               decClientInfo->mMsgHearder.mark[2] != 'N')
            {
                if(decClientInfo->errorCount++ > 5)
                {
                    OnClientDisconnected(clientSock);
                    return;
                }

                continue;
            }

            decClientInfo->isProcessMsgHearder=true;
        }

        if(!decClientInfo->isProcessMsgHearder ||
           (decClientInfo->isProcessMsgHearder &&
            decClientInfo->buffer.GetDataLen() < decClientInfo->mMsgHearder.compLength))
            return;

        wxMemoryBuffer srcDataBuffer = DecompressWithFastLZ(decClientInfo->buffer.GetData(),
                                                            decClientInfo->mMsgHearder.compLength,
                                                            decClientInfo->mMsgHearder.srcLength);
        decClientInfo->RemoveDataFromMemoryBuffer(0,decClientInfo->mMsgHearder.compLength);
        decClientInfo->isProcessMsgHearder = false;
        decClientInfo->errorCount = 0;

        if((srcDataBuffer.IsEmpty() && decClientInfo->mMsgHearder.msgType == IDD_NETWORK_MSG_HEART) ||
           qChecksum((const char*)srcDataBuffer.GetData(),srcDataBuffer.GetDataLen()) != decClientInfo->mMsgHearder.checknum)
        {
            continue;
        }

        // 网络框架处理json消息
        if(m_NetworkFrameManager)
            m_NetworkFrameManager->OnProcessNetData(decClientInfo,
                                                    decClientInfo->mMsgHearder.msgType,
                                                    srcDataBuffer);
    }
}

void WSignalServer::OnClientDisconnected(wxSocketBase* clientSock)
{
    std::unique_lock lock(m_clientsMutex);
    std::map<wxSocketBase*, ClientInfo*>::iterator iter = m_clients.find(clientSock);
    if(iter != m_clients.end()) {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,
                                            wxString::Format(wxT("连接 %s 已断开。"), (*iter).second->clientName).ToUTF8());

        if(m_curOperClient == (*iter).second)
            m_curOperClient = NULL;

        //(*iter).second->deleteMe();
        delete (*iter).second;
        (*iter).second = NULL;

        m_clients.erase(iter);
    } else {
        CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                            "Unknown client disconnected");
    }
}

ClientInfo* WSignalServer::FindClientName(wxString clientName)
{
    if(clientName == "") return NULL;

    ClientInfo* decClientInfo = NULL;

    std::shared_lock lock(m_clientsMutex);
    std::map<wxSocketBase*, ClientInfo*>::iterator iter = m_clients.begin();
    for(;iter != m_clients.end();++iter)
    {
        if((*iter).second->clientName != clientName)
            continue;

        decClientInfo = (*iter).second;
        break;
    }

    return decClientInfo;
}

void WSignalServer::OnHeartTimeOutTimer(wxTimerEvent& event)
{
    wxDateTime now = wxDateTime::Now();
    wxTimeSpan timeout(0, 0, 10); // 10秒超时

    std::unique_lock lock(m_clientsMutex);
    std::map<wxSocketBase*, ClientInfo*>::iterator iter = m_clients.begin();
    for(;iter != m_clients.end();)
    {
        ClientInfo* info = (*iter).second;

        // 检查是否超时
        if ((now - info->lastActiveTime) > timeout) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_INFO,
                                                wxString::Format(wxT("连接 %s 超时断开。"), info->clientName).ToUTF8());

            if(m_curOperClient == (*iter).second)
                m_curOperClient = NULL;

            //(*iter).second->deleteMe();
            delete (*iter).second;
            (*iter).second = NULL;

            iter = m_clients.erase(iter);
            continue;
        }

        ++iter;
    }
}

bool WSignalServer::SendDataOther(int msgtype,const void* data,size_t len,const char* clientid)
{
    if(data == NULL || len <= 0 || clientid == NULL)
        return false;

    std::shared_lock lock(m_clientsMutex);
    std::map<wxSocketBase*, ClientInfo*>::iterator iter = m_clients.begin();
    for(;iter != m_clients.end();++iter)
    {
        if((*iter).second->clientName == clientid)
            continue;

        (*iter).second->SendData(msgtype,data,len);
    }
}

/// 发送消息
bool WSignalServer::SendData(int msgtype,const void* data,size_t len,const char* clientid)
{
    if(data == NULL || len <= 0)
        return false;

    std::shared_lock lock(m_clientsMutex);
    if(clientid == NULL)
    {
        std::map<wxSocketBase*, ClientInfo*>::iterator iter = m_clients.begin();
        for(;iter != m_clients.end();++iter)
            (*iter).second->SendData(msgtype,data,len);
    }
    else
    {
        std::map<wxSocketBase*, ClientInfo*>::iterator iter = m_clients.begin();
        for(;iter != m_clients.end();++iter)
        {
            if((*iter).second->clientName != clientid)
                continue;

            (*iter).second->SendData(msgtype,data,len);
            break;
        }
    }
}

ClientInfo* WSignalServer::FindClientId(wxSocketBase* sock)
{
    if(sock == NULL) return NULL;

    ClientInfo* decClientInfo = NULL;

    std::shared_lock lock(m_clientsMutex);
    std::map<wxSocketBase*, ClientInfo*>::iterator iter = m_clients.find(sock);
    if(iter != m_clients.end())
        decClientInfo = (*iter).second;

    return decClientInfo;
}
